﻿Option Strict On
Option Explicit On
Option Infer On

Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports GenDotNet.TemplateSupport.StandardAttributeExtensions
Imports GenDotNet.Task.Common
Imports GenDotNet.StoredProcModel
Imports <xmlns:kd="http://kadgen.com/Special.xsd">
Imports <xmlns:orm="http://kadgen.com/KADORM.xsd">
Imports System.Xml.Linq
Imports GenDotNet.Model.Common
Imports GenDotNet.TemplateSupport.Strings
Imports GenDotNet.TemplateSupport.SqlServer

Public MustInherit Class SqlServerBase
   Inherits SqlBase

   Protected Overrides Function AliasClause(ByVal name As String, ByVal aliasString As String) As String
      Return name.AliasClause(aliasString)
   End Function

   Protected Overrides Function Aliased(ByVal name As String, ByVal aliasString As String) As String
      Return name.Aliased(aliasString)
   End Function

   Protected Overrides Function FullName(ByVal table As StoredProcModel.ITableData) As String
      Return table.FullName()
   End Function

   Protected Overrides Function FullNameAliased(ByVal table As StoredProcModel.ITableData, ByVal aliasString As String) As String
      Return table.FullNameAliased(aliasString)
   End Function

   Protected Overloads Overrides Function FullNameWithColumn(ByVal table As StoredProcModel.ITableData, ByVal column As StoredProcModel.IColumnData) As String
      Return table.FullNameWithColumn(column)
   End Function

   Protected Overloads Overrides Function FullNameWithColumn(ByVal table As StoredProcModel.ITableData, ByVal columnName As String) As String
      Return table.FullNameWithColumn(columnName)
   End Function

   Protected Overrides Function FullNameWithColumnAndAlias(ByVal table As StoredProcModel.ITableData, ByVal columnName As String, ByVal aliasString As String) As String
      Return table.FullNameWithColumnAndAlias(columnName, aliasString)
   End Function

   Protected Overrides Function EscapedName(ByVal name As String) As String
      Return name.EscapeName()
   End Function

End Class


Namespace SqlServer
   Public Module SqlBaseExtensions

      <System.Runtime.CompilerServices.Extension()> _
      Public Function EscapeName(ByVal name As String) As String
         Return "[" & name & "]"
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function FullName(ByVal table As ITableData) As String
         Return If(String.IsNullOrEmpty(table.Schema) Or table.Schema.EqualsIgnoreCase("dbo"), String.Empty, _
                   "[" & table.Schema & "].") & _
                   "[" & table.Name & "]"
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function FullNameAliased(ByVal table As ITableData, ByVal aliasString As String) As String
         Return table.FullName.Aliased(aliasString)
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function FullNameWithColumn(ByVal table As ITableData, ByVal column As IColumnData) As String
         Return table.FullName & ".[" & column.Name & "]"
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function FullNameWithColumn(ByVal table As ITableData, ByVal columnName As String) As String
         Return table.FullName & ".[" & columnName & "]"
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function FullNameWithColumnAndAlias(ByVal table As ITableData, ByVal columnName As String, ByVal aliasString As String) As String
         Return table.FullName & "." & columnName.Aliased(aliasString)
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function Aliased(ByVal name As String, ByVal aliasString As String) As String
         If name.StartsWith("[") Then
            Return name & AliasClause(name, aliasString)
         Else
            Return "[" & name & "]" & AliasClause(name, aliasString)
         End If
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function AliasClause(ByVal name As String, ByVal aliasString As String) As String
         Return If(name.EqualsIgnoreCase(aliasString), String.Empty, " As " & aliasString)
      End Function

      <System.Runtime.CompilerServices.Extension()> _
      Public Function ChildJoin(ByVal child As IChildData) As String
         ' this is sort of kludgy and does not handle multi-step joins
         Dim firstKey = child.ChildKeys(0)
         If child.ChildKeys(0).ParentTable Is firstKey.ChildTable Then
            ' we are working up the join, so we need to alias the parent, but we 
            ' don't have a parent alias so we are using the child alias
            Dim parentAlias = firstKey.ChildAlias
            Return " INNER JOIN " & firstKey.ParentTable.FullNameAliased(parentAlias) & " ON " & _
                     (From key In child.ChildKeys _
                        Select parentAlias & "." & _
                         key.ParentColumnName.EscapeName & " = " & _
                         key.ChildTable.FullName & "." & _
                         key.ChildColumnName.EscapeName).ConcatenateWith(andString.WithSpaceAround)
         Else
            Return " INNER JOIN " & child.ChildKeys(0).ParentTable.FullName & " ON " & _
                     (From key In child.ChildKeys _
                        Select key.ParentTable.Name.EscapeName & "." & _
                         key.ParentColumnName.EscapeName & " = " & _
                         key.ChildTable.FullName & "." & _
                         key.ChildColumnName.EscapeName).ConcatenateWith(andString.WithSpaceAround)
         End If
      End Function

   End Module

End Namespace
